/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package main.KBProcess;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Formatter;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import main.KBProcess.Element.ElementType;
import main.Ontology.DefaultElementOntologyFactory;
import main.Ontology.ElementOntologyFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * 
 * @author Isaac Osesina
 */
public class UTEES_Parser_SAX {
	private javax.xml.parsers.SAXParser parser;
	String kbFilePath;
	Formatter output;
	Formatter entityList;
	int docPos;
	KnowledgeBase thisKB = new DefaultKnowledgeBase();
	KnowledgeBaseDocument kbDoc = null;
	DefaultElement element = null;
	int KBCharCnt = 0;
	int entityCnt;
	UTEES_MatchTable documentOntology;
	String ontologyFileName;
	Set<Integer> docsToSkip;
	Set<Integer> docsToAccept;
	
	private ElementOntologyFactory elementOntologyFactory;

	public UTEES_Parser_SAX(ElementOntologyFactory elementOntologyFactory)
			throws javax.xml.parsers.ParserConfigurationException,
			org.xml.sax.SAXException {
		javax.xml.parsers.SAXParserFactory factory = javax.xml.parsers.SAXParserFactory
				.newInstance();
		factory.setNamespaceAware(true);
		this.parser = factory.newSAXParser();
		this.elementOntologyFactory = elementOntologyFactory;
	}

	public String getOntologyFileName() {
		return ontologyFileName;
	}

	public UTEES_MatchTable getDocumentOntology() {
		return documentOntology;
	}

	public void readKB(File thisFile, UTEES_MatchTable docOntology,
			Set<Integer> docsToSkip, Set<Integer> docsToAccept)
			throws java.io.IOException, org.xml.sax.SAXException {
		File file = thisFile;
		if (!file.exists()) {
			String errorMsg = "Error- Can't open " + thisFile;
			throw new java.io.FileNotFoundException(errorMsg);
		}
		FileInputStream fis = new java.io.FileInputStream(file);
		this.documentOntology = docOntology;
		// documentOntology.dumpList();
		this.docsToSkip = docsToSkip;
		this.docsToAccept = docsToAccept;
		// System.out.println("fis:"+ fis);

		this.doRead(fis);
		// this.doRead(file);

	}

	private void doRead(java.io.File file) throws java.io.IOException,
			org.xml.sax.SAXException {
		StringBuilder out = new StringBuilder();
		String read = "";
		try {
			BufferedReader in = new BufferedReader(new FileReader(file));
			while ((read = in.readLine()) != null) {
				// if(read != null)
				// {
				// read =
				// read.replaceAll("[^ A-Za-z0-9!\"#$%&'()*+,./:;<=>?@\\_`{|}~-]",
				// "");
				// }
				out.append(read);
			}
			in.close();
		} catch (Exception e) {
			System.err.println("load: " + e);
		}
		String str = out.toString();
		this.parser.parse(
				new InputSource(new ByteArrayInputStream(str.getBytes())),
				new Handler());
		// this.parser.parse( new InputSource(new StringReader(str) ), new
		// Handler() );
	}

	private void doRead(FileInputStream fis) throws java.io.IOException,
			org.xml.sax.SAXException {
		this.parser.parse(fis, new Handler());

	}

	public KnowledgeBase getParsedKB() {
		return thisKB;
	}

	public int getKBCharCnt() {
		return KBCharCnt;
	}

	public void shutDown() {
		output.format("****PARSER STOPPED*****\n");
		output.flush();
		System.exit(0);
	}

	// ===========================================================
	// Methods in SAX DocumentHandler
	// ===========================================================

	private class Handler extends org.xml.sax.helpers.DefaultHandler {
		// Data Members
		String currentElement = null; // current element name
		String docType;
		String docID;
		int tagIndex;
		StringBuffer docContent;

		private boolean firstElement = true;
                    private String documentLanguage;
                    private String documentCategory;

		@Override
		public void startElement(String uri, String lname, String qname,
				org.xml.sax.Attributes attributes)
				throws org.xml.sax.SAXException {
			if (this.firstElement) {
				if (!lname.equalsIgnoreCase("ExpertCoding")) {
					throw new IllegalArgumentException("Not a UTEES_KB file");
				} else
					this.firstElement = false;
			}

			if (lname.equalsIgnoreCase("ExpertCoding")) {
				// ontologyFileName = attributes.getValue("Ontology");
				// documentOntology = new UTEES_MatchTable(ontologyFileName);
			}

			else if (lname.equalsIgnoreCase(documentOntology.getEntryAt(0))) // KBDocType
			{
				docType = documentOntology.getEntryAt(0);
				docID = attributes.getValue("DocID");
				int id = Integer.parseInt(docID);
				if ((docsToAccept != null && docsToAccept.contains(id))
						|| (docsToSkip != null && !docsToSkip.contains(id))) {
					docPos = 0;
					kbDoc = new DefaultKnowledgeBaseDocument(id, documentOntology, elementOntologyFactory);
					docContent = new StringBuffer();
					entityCnt = 0;
				}
			}

			else {
				currentElement = qname;
				documentOntology.findMatch(docType + "." + currentElement);
				tagIndex = documentOntology.getMatchIndex();
			}
		}

		@Override
		public void endElement(String uri, String lname, String qname)
				throws org.xml.sax.SAXException {
			if (lname.equalsIgnoreCase(documentOntology.getEntryAt(0))) {
				kbDoc.setDocText(docContent.toString());
				kbDoc.setEntityCnt(entityCnt);
				KBCharCnt = KBCharCnt + docContent.length();


				// System.out.println(kbDoc.getDocText());
				thisKB.addKBDoc(kbDoc);
			}

		}

		@Override
		public void characters(char[] data, int start, int length)
				throws org.xml.sax.SAXException {
			if (this.currentElement != null
					&& !this.currentElement.equalsIgnoreCase(documentOntology
							.getEntryAt(0))) {
				String value = new String(data, start, length);
				if (!value.equals("\n")) {
					value = escapeXML(value);
					element = new DefaultElement(elementOntologyFactory);
					if (tagIndex < 0)
						currentElement = "Context";
					element.setType(currentElement
							.equalsIgnoreCase(main.KBProcess.Element.CONTEXT) ? ElementType.CONTEXT
							: ElementType.ENTITY);
					element.setLabel(currentElement);
					element.setValue(value);
					element.setIndexOf(docPos);
					element.setLabelIndex(tagIndex);
					element.setDocID(Integer.parseInt(docID));
					kbDoc.addElement(element);
					if (!currentElement.equalsIgnoreCase("Context"))
						entityCnt++;
					docContent.append(value);
					// System.out.println(value +" Start:"+docPos +
					// " Idx:"+labelIndex);
					docPos = docPos + length;
				}
			}
		}

		private String escapeXML(String s) {
			s = s.replaceAll("&lt;", "<");
			s = s.replaceAll("&gt;", ">");
			s = s.replaceAll("&amp;", "&<");
			s = s.replaceAll("&quot;", "\"");
			s = s.replaceAll("&apos;", "'");
			return s;
		}

	}

	public static void main(String[] args) throws IOException, SAXException,
			ParserConfigurationException {

		System.out
				.println("====================THIS IS JUST A TEST====================");
		UTEES_Parser_SAX newParser = new UTEES_Parser_SAX(new DefaultElementOntologyFactory());

		String ontologyFileName = "Files/EnglishObituaryV3.txt";
		String KBFileName = "Files/KB200.txt";
		File ontologyFile = new File(ontologyFileName);
		File KBFile = new File(KBFileName);
		UTEES_MatchTable documentOntology = new UTEES_MatchTable(ontologyFile);
		newParser.readKB(KBFile, documentOntology, null, null);
		// System.out.println(newParser.getParsedKB().getKBDoc(0).Elements.size());
		// ("C:/Documents and Settings/Isaac Osesina/My Documents/UALR/Info. Extraction/Spring 2010/UTEES_Version_11v2/Files/kb2.txt");

	}

}
